//*********************************************************
//
//    Copyright (c) Microsoft. All rights reserved.
//    This code is licensed under the Apache License, Version 2.0.
//    THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
//    ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
//    IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
//    PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

namespace Microsoft.Research.ScientificWorkflow.TridentUtilities
{
    #region Using Directives
    using System;
    using System.Globalization;
    using System.Text;
    using System.Windows;
    using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;
    using Microsoft.Practices.EnterpriseLibrary.Logging;
    using SR = Microsoft.Research.DataLayer;
    #endregion

    /// <summary>
    /// TridentErrorHandler
    /// </summary>
    public static class TridentErrorHandler
    {
        /// <summary>
        /// Generic error message to be displayed in the case of general exceptions.
        /// </summary>
        private static string genericErrorMsg = TridentCommonResourceManager.GetString("GeneralError");
        
        /// <summary>
        /// Logs the Exception.
        /// </summary>
        /// <param name="exception">Exception</param>
        public static void HandleUIException(Exception exception)
        {
            ExceptionPolicy.HandleException(exception, "HandleAndLog");
        }

        /// <summary>
        /// Throws TridentCustomException
        /// </summary>
        /// <param name="errorNumber">double error Number</param>
        /// <param name="errorMessage">error megssage.</param>
        /// <returns></returns>
        public static TridentCustomException ThrowTridentCustomException(
            double errorNumber,
            string errorMessage)
        {
            throw new TridentCustomException(errorNumber, errorMessage);
        }

        /// <summary>
        /// Handle and Logs the Exception and rethrow as TridentCustomException
        /// </summary>
        /// <param name="exception"></param>
        /// <param name="errorCode"></param>
        /// <param name="customMessage"></param>
        public static void HandleAndThrowBusinessLogicException(
            Exception exception,
            double errorCode,
            string customMessage)
        {
            TridentCustomException customException = new TridentCustomException(errorCode, customMessage, exception);
            customException.ErrorCaption = TridentResourceManager.GetString("TridentErrorString");

            StringBuilder logString = new StringBuilder();
            logString.Append("Error Number: ");
            logString.Append(errorCode);
            logString.Append(" Error Message: ");
            logString.Append(customMessage);
            logString.Append(" Occured Please check the below Stack trace.");

            Logger.Write(logString);
            ExceptionPolicy.HandleException(exception, "HandleAndLog");
            throw customException;
        }

        /// <summary>
        /// Handles the trident custom exception in UI.
        /// </summary>
        /// <param name="exception">The exception.</param>
        public static void HandleTridentCustomExceptionInUI(TridentCustomException exception)
        {
            HandleTridentCustomExceptionInUI(null, exception);
        }

        /// <summary>
        /// Handles the trident custom exception in UI.
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="exitApplication">if set to <c>true</c> [exit application].</param>
        public static void HandleTridentCustomExceptionInUI(TridentCustomException exception, bool exitApplication)
        {
            HandleTridentCustomExceptionInUI(null, exception, exitApplication);
        }

        /// <summary>
        /// Handles the trident custom exception in UI.
        /// </summary>
        /// <param name="exception">The exception object.</param>
        /// <param name="owner">The owner.</param>
        public static void HandleTridentCustomExceptionInUI(Window owner, TridentCustomException exception)
        {
            HandleTridentCustomExceptionInUI(owner, exception, true);
        }

        /// <summary>
        /// Handles the trident custom exception in UI.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="exception">The exception.</param>
        /// <param name="exitApplication">if set to <c>true</c> [exit application].</param>
        public static void HandleTridentCustomExceptionInUI(Window owner, TridentCustomException exception, bool exitApplication)
        {            
            ShowMessage(owner, exception.Message);
            if (exitApplication && exception.ErrorNumber.Equals(TridentErrorConstants.ErrorNumber1000000072.ToString(CultureInfo.InvariantCulture)))
            {
                Environment.Exit(0);
            }
        }

        /// <summary>
        /// Processes the known exceptions.
        /// </summary>
        /// <param name="exception">The exception.</param>
        public static void ProcessKnownExceptionsInBusinessLogic(Exception exception)
        {
            if (exception is SR.NotAuthenticatedException)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(exception,
                TridentErrorConstants.ErrorNumber1000000072,
                TridentCommonResourceManager.GetString("NotAuthenticatedError"));
            }
            else if (exception is System.Security.SecurityException)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(exception,
                TridentErrorConstants.ErrorNumber1000000069,
                TridentCommonResourceManager.GetString("WorkflowPermissionDenied"));
            }
            else if (exception is SR.BackendStorageException)
            {
                TridentErrorHandler.HandleAndThrowBusinessLogicException(exception,
                TridentErrorConstants.ErrorNumber1000000074,
                TridentCommonResourceManager.GetString("RegistryConnectionLost"));
            }            
        }

        /// <summary>
        /// Handles the known exceptions in UI.
        /// </summary>
        /// <param name="exception">The exception.</param>
        public static void HandleKnownExceptionsInUI(Exception exception)
        {
            HandleKnownExceptionsInUI(null, exception, genericErrorMsg);
        }

        /// <summary>
        /// Handles the known exceptions in UI.
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="exitApplication">if set to <c>true</c> [exit application].</param>
        public static void HandleKnownExceptionsInUI(Exception exception, bool exitApplication)
        {
            HandleKnownExceptionsInUI(null, exception, genericErrorMsg, exitApplication);
        }

        /// <summary>
        /// Handles the known exceptions in UI.
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="genericMessage">The generic message.</param>
        public static void HandleKnownExceptionsInUI(Exception exception, String genericMessage)
        {
            HandleKnownExceptionsInUI(null, exception, genericMessage);
        }

        /// <summary>
        /// Handles the known exceptions in UI.
        /// </summary>
        /// <param name="exception">The exception.</param>
        /// <param name="genericMessage">The generic message.</param>
        /// <param name="exitApplication">if set to <c>true</c> [exit application].</param>
        public static void HandleKnownExceptionsInUI(Exception exception, String genericMessage, bool exitApplication)
        {
            HandleKnownExceptionsInUI(null, exception, genericMessage, exitApplication);
        }

        /// <summary>
        /// Handles the known exceptions in UI.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="exception">The exception.</param>
        public static void HandleKnownExceptionsInUI(Window owner, Exception exception)
        {
            HandleKnownExceptionsInUI(owner, exception, genericErrorMsg);
        }

        /// <summary>
        /// Handles the known exceptions in UI.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="exception">The exception.</param>
        /// <param name="exitApplication">if set to <c>true</c> [exit application].</param>
        public static void HandleKnownExceptionsInUI(Window owner, Exception exception, bool exitApplication)
        {
            HandleKnownExceptionsInUI(owner, exception, genericErrorMsg, exitApplication);
        }

        /// <summary>
        /// Processes the known UI exceptions.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="exception">The exception.</param> 
        /// <param name="genericMessage">The generic message.</param>
        public static void HandleKnownExceptionsInUI(Window owner, Exception exception, String genericMessage)
        {
            HandleKnownExceptionsInUI(owner, exception, genericMessage, true);
        }

        /// <summary>
        /// Handles the known exceptions in UI.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="exception">The exception.</param>
        /// <param name="genericMessage">The generic message.</param>
        /// <param name="exitApplication">if set to <c>true</c> [exit application].</param>
        public static void HandleKnownExceptionsInUI(Window owner, Exception exception, String genericMessage, bool exitApplication)
        {
            if (exception is SR.NotAuthenticatedException)
            {
                ShowMessage(owner, TridentCommonResourceManager.GetString("NotAuthenticatedError"));
                if (exitApplication)
                {
                    Environment.Exit(0);
                }
            }
            else if (exception is System.Security.SecurityException)
            {
                ShowMessage(owner, TridentCommonResourceManager.GetString("WorkflowPermissionDenied"));
            }
            else if (exception is SR.BackendStorageException)
            {
                ShowMessage(owner, TridentCommonResourceManager.GetString("RegistryConnectionLost"));
            }
            else
            {
                TridentErrorHandler.HandleUIException(exception);
                ShowMessage(owner, genericMessage);
            }
        }

        /// <summary>
        /// Shows the message.
        /// </summary>
        /// <param name="owner">The owner.</param>
        /// <param name="message">The message.</param>
        private static void ShowMessage(Window owner, String message)
        {
            try
            {
                if (owner != null)
                {
                    TridentMessageBox.ShowTridentErrorMessageBox(owner, message);
                }
                else
                {
                    TridentMessageBox.ShowTridentErrorMessageBox(message);
                }
            }
            catch (Exception)
            {
            }
        }
    }
}
